package com.alinesno.cloud.operation.cmdb.third.wechat.impl;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.alinesno.cloud.operation.cmdb.common.constants.OrderSendScopeEnum;
import com.alinesno.cloud.operation.cmdb.common.constants.OrderStatusEnum;
import com.alinesno.cloud.operation.cmdb.common.constants.ParamsEnum;
import com.alinesno.cloud.operation.cmdb.common.constants.RunerEnum;
import com.alinesno.cloud.operation.cmdb.common.util.DateUtil;
import com.alinesno.cloud.operation.cmdb.common.util.UserUtils;
import com.alinesno.cloud.operation.cmdb.entity.OrderInfoEntity;
import com.alinesno.cloud.operation.cmdb.entity.OrdersEntity;
import com.alinesno.cloud.operation.cmdb.entity.UserEntity;
import com.alinesno.cloud.operation.cmdb.entity.WechatTemplateEntity;
import com.alinesno.cloud.operation.cmdb.repository.OrderInfoRepository;
import com.alinesno.cloud.operation.cmdb.repository.OrderRepository;
import com.alinesno.cloud.operation.cmdb.repository.UserRepository;
import com.alinesno.cloud.operation.cmdb.repository.WechatTemplateRepository;
import com.alinesno.cloud.operation.cmdb.service.ParamsService;
import com.alinesno.cloud.operation.cmdb.service.UserService;
import com.alinesno.cloud.operation.cmdb.third.wechat.WechatConfig;
import com.alinesno.cloud.operation.cmdb.third.wechat.WechatService;
import com.alinesno.cloud.operation.cmdb.web.bean.OrderInfoBean;

import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;

/**
 * 服务服务
 *
 * @author LuoAnDong
 * @since 2018年8月5日 下午5:57:36
 */
@Service
public class WechatServiceImpl implements WechatService {

	private static final Logger logger = LoggerFactory.getLogger(WechatServiceImpl.class);

	@Autowired
	private WechatConfig wechatConfig;

	@Value("${wechat.host}")
	private String wechatHost;
	
	@Value("${wechat.link.out-time}")
	private String linkOuttime ;
	
	@Value("${wechat.link.score}")
	private String linkScore ;

	@Autowired
	private OrderInfoRepository orderInfoRepository; // 订单详情服务

	@Autowired
	private OrderRepository orderRepository; // 订单服务

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private UserService userService ; // 用户服务 

	@Autowired
	private WechatTemplateRepository wechatTemplateRepository;
	
	@Autowired
	private ParamsService paramsService ; 
	
//	private int outTime = 0 ; 
//	
//	private int getOuttime() {
//		if(outTime == 0) {
//			outTime = paramsService.findParamByNameToInt(ParamsEnum.ORDER_OUTTIME.getCode())  ; 
//		}
//		return outTime ; 
//	}

	/**
	 * 通过订单id查询订单信息
	 *
	 * @return
	 */
	private OrderInfoBean getOrderInfo(String orderId) {
		OrdersEntity orderEntity = orderRepository.findByOrderId(orderId);
		OrderInfoEntity orderInfo = orderInfoRepository.findById(orderEntity.getInfoId()).get();
		OrderInfoBean bean = new OrderInfoBean();
		BeanUtils.copyProperties(orderEntity, bean);
		BeanUtils.copyProperties(orderInfo, bean);
		
		Optional<UserEntity> userEntity = userRepository.findById(orderEntity.getUserId()); 
		if(userEntity != null) {
			bean.setUserNickName(userEntity.get().getNickname());
		}

		String goodsName = bean.getGoodsName() ; 
		if(StringUtils.isNoneBlank(goodsName) && goodsName.contains("#")) {
			bean.setGoodsName(goodsList(goodsName));
		}
		
		String status = bean.getSendStatus();
		bean.setSendStatusLabel(OrderStatusEnum.getStatus(status).getText());
		return bean;
	}
	
	/* (non-Javadoc)
	 * @see com.linesno.training.business.run.wechat.impl.WechatService#sendTaskReceive(java.lang.String)
	 */
	@Override
	@Async("processExecutor")
	public void sendTaskReceive(String orderId) {
		OrderInfoBean orderInfo = getOrderInfo(orderId);
		Optional<UserEntity> users = userRepository.findById(orderInfo.getUserId()) ; 
		if(isError(users, orderId, orderInfo.getUserId(), null)) {
			return ; 
		}
		UserEntity userEntity = users.get();
		
		String firstText = "" ; 
		String url = null ; 
		String remark = null ; 
	
		//订单处理
		if(OrderStatusEnum.ORDER_OUTTIME.getCode().equals(orderInfo.getSendStatus())) { //超时订单
			firstText = String.format("你的任务【%s】已超时,可以加价或者删除 \r\n", orderInfo.getGoodsName()) ; //, managers.get().getPhone());
			url = getLink(linkOuttime , orderId)  ; 
			remark = "\r\n订单可以加价或者删除."; 
		}else {
			Optional<UserEntity> managers  = userRepository.findById(orderInfo.getReceiveManagerId()) ; 
			if(isError(managers, orderId, null , orderInfo.getReceiveManagerId())) {
				return ; 
			}
			if(OrderStatusEnum.ORDER_FINISH.getCode().equals(orderInfo.getSendStatus())) { //结束订单,显示评分
				remark = "\r\n请评价本次服务."; 
				url = getLink(linkScore , orderId) ; 
			}
			firstText = String.format("你的任务【%s】已被接单,正在火速赶往，请耐心等待\r\n接单人:%s\r\n", orderInfo.getGoodsName(), UserUtils.realName(managers.get())) ; // managers.get().getPhone());
		}
		
		//发送消息 
		try {
			WxMpTemplateMessage templateMessage = wechatConfig.sendChangOrder(url ,
					userEntity.getOpenId(),
					firstText,
					OrderStatusEnum.getStatus(orderInfo.getSendStatus()).getText(),
					DateUtil.getFullChinesePatternNow(),
					remark) ;

			String tip = wechatConfig.getInstance().getTemplateMsgService().sendTemplateMsg(templateMessage);
			this.saveSendTemplate(tip, "order-change" , userEntity.getId());

			logger.info("推送订单[{}]至[{}]成功:{}", orderId, userEntity.getPhone());
		} catch (WxErrorException e) {
			logger.error("推送订单[{}]至[{}]失败:{}", orderId, userEntity.getPhone(), e);
		}
	}
	
	private String getLink(String link , String orderId) {
		return link.endsWith("/")?link+orderId:(link+"/"+orderId) ;  
	}

	/**
	 * 记录订单错误信息
	 * @param t
	 * @param orderId
	 * @param userId
	 * @param managerId
	 * @return
	 */
	private <T> boolean isError(Optional<T> t , String orderId , String userId , String managerId) {
		if(!t.isPresent()) { //设置订单错误,更新订单状态
			String errorMsg =  null ; 
			if(StringUtils.isNoneBlank(userId)) {
				errorMsg = String.format("订单[%s],查询用户[%s]为空,订单消息无法发送.", orderId , userId) ; 
			}else {
				errorMsg = String.format("订单[%s],查询配送员[%s]为空,订单消息无法发送.", orderId , userId) ; 
			}
			logger.error(errorMsg);
			OrdersEntity order = orderRepository.findByOrderId(orderId) ; 
			order.setErrorMsg(errorMsg); 
			order.setSendStatus(OrderStatusEnum.ORDER_ERROR.getCode()); 
			order.setUpdateTime(new Timestamp(System.currentTimeMillis()));
			orderRepository.save(order) ; 
			return true ; 
		}
		return false ;  
	}

	/* (non-Javadoc)
	 * @see com.linesno.training.business.run.wechat.impl.WechatService#sendTaskMessage(java.lang.String, java.lang.String)
	 */
	@Override
	@Async("processExecutor")
	public void sendTaskMessage(String orderId, String masterCode) {
        this.sendTaskMessageToSchool(orderId , null , masterCode) ;
    }

	/* (non-Javadoc)
	 * @see com.linesno.training.business.run.wechat.impl.WechatService#sendTaskMessageToSchool(java.lang.String, java.lang.String, java.lang.String, boolean)
	 */
	@Override
	@Async("processExecutor")
	public void sendTaskMessageToSchool(String orderId , String salaId , String masterCode , String orderUserId , boolean isAll) {

		List<UserEntity> users = null ;
        if(StringUtils.isBlank(salaId)){
        		if(isAll) {
        			users = userService.findAllMember(masterCode , orderUserId) ; 
        		}else {
				users = userRepository.findAllByMasterCodeAndFieldPropOrderByIntegralDesc(masterCode , RunerEnum.STATUS_RUNMAN.getCode()) ; // 查询所有的人员
        		}
        }else{
            users = new ArrayList<UserEntity>() ; //单独推送给销售员
            UserEntity user = userRepository.findById(salaId).get();
            users.add(user) ;
        }

		if (users != null) {
			
			OrderInfoBean orderInfo = getOrderInfo(orderId);

			for (UserEntity e : users) {

				logger.info("消息推送业务员:{},订单号:{}", ToStringBuilder.reflectionToString(e), orderId);

				String url = wechatHost + "/order_task/" + orderId;
				String user = e.getOpenId();
				
				if(StringUtils.isBlank(user)) {
					logger.error("用户{}的openId为空,推送任务订单失败!", e.getPhone());
					continue ; 
				}

				String firstText = String.format("您好，您收到了一个新任务,请尽快接单处理\r\n");
				StringBuffer remark = new StringBuffer() ; 
			
				if(StringUtils.isNoneBlank(orderInfo.getGetAddress())) {
					remark.append("任务地址: " + orderInfo.getGetAddress() + "\r\n") ; 
				}
				remark.append("收货地址: " + orderInfo.getReceiveAddress()+ "\r\n") ; 
				
				if(orderInfo.getSendTime() != null) {
					remark.append("配送时间:"+ DateUtil.formatDate(orderInfo.getSendTime(), DateUtil.FULL_CHINESE_PATTERN) +"\r\n") ; 
				}

				int outTime = paramsService.findParamByNameToInt(ParamsEnum.ORDER_OUTTIME.getCode(), orderInfo.getMasterCode())  ; 
				try {
					WxMpTemplateMessage templateMessage = wechatConfig.sendNewOrder(url, user, firstText, orderId,
							orderInfo.getUserNickName(),
							orderInfo.getGoodsName(),
							orderInfo.getTotalPay(), 
							DateUtil.getOutTimeDate(orderInfo.getAddTime(), outTime),
							remark.toString());

					String tip = wechatConfig.getInstance().getTemplateMsgService().sendTemplateMsg(templateMessage);
					this.saveSendTemplate(tip, "order-new" , e.getId());

					logger.info("推送订单[{}]消息[{}]至[{}]成功", orderId, url, user);
				} catch (WxErrorException e1) {
					this.saveSendTemplate(firstText+remark, "order-send-error" , e.getId() , e1.getMessage());
					logger.error("推送订单[{}]消息[{}]至[{}]失败:{}", orderId, url, user, e1);
				}
			}

		}
	}

	private void saveSendTemplate(String tip, String string, String id) {
		this.saveSendTemplate(tip, string, id , null);
	}

	/**
	 * 保存发送结果
	 * @param tip
	 * @param prop
	 * @param userId
	 */
	private void saveSendTemplate(String tip , String prop , String userId , String errorMsg) {
		WechatTemplateEntity t = new WechatTemplateEntity();
		t.setTemplateContent(tip);
		t.setErrorMessage(errorMsg);
		t.setAddTime(new Timestamp(System.currentTimeMillis()));
		t.setFieldProp(prop);
		t.setUserId(userId);
		wechatTemplateRepository.save(t);
	}

	/* (non-Javadoc)
	 * @see com.linesno.training.business.run.wechat.impl.WechatService#sendNoticeToApplyMan(com.linesno.training.business.run.entity.UserEntity, boolean)
	 */
	@Override
	@Async("processExecutor")
	public void sendNoticeToApplyMan(UserEntity u, boolean b) {
		String url = null ; 
		String user = u.getOpenId() ; 
		String firstText = b?"你的申请已通过,恭喜你成为一名镖师:-),请注意接收微信订单信息.\r\n":"你的申请未通过,感谢你对平台的支持." ; 
		String dealMan = "云主机管理系统" ;
		String date = DateUtil.getChinesePatternNow() ; 
		String result = b?"申请通过":"申请不通过" ;
		String remark = null ; 
		logger.debug("发送通知至申请人员:{} , 结果:{}" , u , result);
		try {
			WxMpTemplateMessage msg = wechatConfig.sendFeelbackNotice(url, user, firstText, dealMan, date, result, remark)  ;
			String tip = wechatConfig.getInstance().getTemplateMsgService().sendTemplateMsg(msg) ; 
			this.saveSendTemplate(tip, "feelback" , u.getId());
		} catch (WxErrorException e) {
			logger.error("推送申请结果通知消息至[{}]失败:{}", user, e);
		}
	}
	
	private String goodsList(String goods) {
		return StringUtils.isNoneBlank(goods)?"\r\n"+goods.replaceAll("#", "\r\n")+"\r\n":"没有商品信息." ; 
	}

	/**
	 * 获取用户姓名
	 * @param u
	 * @return
	 */
//	private String realName(UserEntity u) {
//		return StringUtils.isNotBlank(u.getRealName())?u.getRealName()+"("+u.getPhone()+")":u.getPhone(); 
//	}

	/* (non-Javadoc)
	 * @see com.linesno.training.business.run.wechat.impl.WechatService#sendTaskMessageToSchoolAllPerson(java.lang.String, java.lang.String)
	 */
	@Override
	@Async("processExecutor")
	public void sendTaskMessageToSchoolAllPerson(String orderId , String scope) {
		Assert.hasLength(orderId , "订单id不能为空.");
		OrdersEntity order = orderRepository.findByOrderId(orderId) ; 
		
		Assert.notNull(order , "订单不能为空.");
		Assert.hasLength(order.getMasterCode(), "订单所属机房不能为空.");
		
		boolean isAll = OrderSendScopeEnum.ALL.getCode().equals(scope)?true:false ; 
		
		this.sendTaskMessageToSchool(orderId, null , order.getMasterCode() , order.getUserId() ,  isAll);
	}

	/* (non-Javadoc)
	 * @see com.linesno.training.business.run.wechat.impl.WechatService#sendTaskMessageToSchool(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	@Async("processExecutor")
	public void sendTaskMessageToSchool(String orderId, String salaId , String masterCode) {
		
		Assert.hasLength(orderId , "订单id不能为空.");
		Assert.hasLength(masterCode, "订单所属机房不能为空.");
		
		this.sendTaskMessageToSchool(orderId, null , masterCode, null ,  false);
	}

	@Override
	public WxMpUser userInfo(String openId) throws WxErrorException {
		WxMpUser user = wechatConfig.getInstance().getUserService().userInfo(openId,null);
		return user ;
	}

	@Override
	public List<UserEntity> userList(String nextOpenId) {
		WxMpUserList wxUserList;
		List<UserEntity> users = new ArrayList<UserEntity>() ; 
		
		try {
			wxUserList = wechatConfig.getInstance().getUserService().userList(nextOpenId);
			List<String> opendIds = wxUserList.getOpenids() ; 
			for(String openId : opendIds) {
				UserEntity user = new UserEntity() ; 
				WxMpUser wxUser = this.userInfo(openId) ; 
				BeanUtils.copyProperties(wxUser, user);
				users.add(user) ; 
			}
		} catch (WxErrorException e) {
			logger.error("获取用户列表失败:{}" , e);
		}
		
		return users ;
	}

}
